package org.vectrics.skill.struts;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.TreeSet;

import javax.servlet.jsp.JspException;

import org.apache.ecs.html.Font;
import org.apache.ecs.html.IMG;
import org.apache.ecs.html.Input;
import org.apache.log4j.Category;
import org.vectrics.SystemException;
import org.vectrics.common.html.BorderTable;
import org.vectrics.common.html.Cell;
import org.vectrics.common.html.Form;
import org.vectrics.common.html.Row;
import org.vectrics.common.html.Table;
import org.vectrics.common.html.TextHelper;
import org.vectrics.common.tree.TreeHelper;
import org.vectrics.recruiter.RecruitServiceLocator;
import org.vectrics.recruiter.web.tags.SkillGui;
import org.vectrics.skill.Skill;
import org.vectrics.skill.SkillChildComparator;
import org.vectrics.skill.SkillException;
import org.vectrics.skill.SkillRating;
import org.vectrics.skill.SkillRatingSet;
import org.vectrics.skill.SkillScoringMethod;
import org.vectrics.skill.SkillSetUtil;
import org.vectrics.struts.Request;
import org.vectrics.struts.VectricsTagSupport;

abstract public class EnterDetailSkillsTagAbstract extends VectricsTagSupport {

	private static final long serialVersionUID = -6335019516042451445L;

	private static Category log = Category.getInstance(EnterDetailSkillsTagAbstract.class);
    //private RecruitUserProfile userProfile = null;
    public static String ENTRY_TYPE_PARAM = "entry_type";
    Skill rootSkill = null;
    boolean forceAllChildrenToDisplay = false;
    //private Job job = null;
    
    public static int USER_OBJECT_TYPE = 0;
    public static int JOB_OBJECT_TYPE = 0;
    private int tableWidth = 500;
    private int objectType = USER_OBJECT_TYPE; 
    private String contextPath = null;
    private String skillSection = null;
    private Skill skillBranch = null;
    
    public EnterDetailSkillsTagAbstract() {
    	//
    }

    final  protected SkillRatingSet getSkillRatingSet(Request request) throws SkillException {
    	SkillRatingSet set = SkillWebUtils.getSkillRatingSet(request);
    	if (set == null) {
    		throw new SkillException("SkillRatingSet was not previously attached to session"
    				+ " attribute - make sure PrepareWizardAction is called first");
    	}
    	return(set);
    }
    
    
    abstract protected String getFormAction();
    abstract protected String getOwnerObjectId();
    abstract protected int getWidth();
    abstract protected boolean getShowViewChildren();
    abstract protected boolean getShowYesNo();
    abstract protected boolean getShowYears();
    abstract protected boolean getShowChildren();
    abstract protected boolean getShowRating();  // User only
    abstract protected void addHiddenInputs(Form form);
    abstract protected boolean alwaysShowLevelEntry();

    protected String getContextPath() {
    	return(contextPath);
    }
    
    public String makeStartTag() {
    	
        String html = ""; 
    	try {
    		if (this.getOwnerObjectId() == null) {
    			log.error("ownerObjectId not specified by derived class");
    			throw new JspException("ownerObjectId not specified by derived class");
    		}
    		
    		log.debug("----------------------------------------------------------------------");
    		log.debug("doStartTag() - called");
    		Request request = this.getRequest();
			contextPath = request.getContextPath();
	
	        Collection skillSet = null;
            log.debug("doRender() - current level = " + SkillWebUtils.getLevel(request));
	        
	        SkillRatingSet skillRatingSet = null;
	        try {
	        	skillRatingSet = getSkillRatingSet(request);
	        } catch (SkillException se) {
	        	log.error("SkillException calling getSkillRating()", se);
	        	throw new JspException("SkillException calling getSkillRating()", se);
	        }
	        skillSection = SkillWebUtils.getSkillSection(request);
        	if (skillSection == null) {
        		rootSkill = RecruitServiceLocator.getSkillProvider().getRootSkill();
        	}
        	else {
        		skillBranch = RecruitServiceLocator.getSkillProvider().findSkill(skillSection);
        		log.debug("We are only editing a skill section, the root will"
        				+ " be top of that section");
        		rootSkill = skillBranch.getSkillParent();
        	}
        	
	        Skill parentSkill = rootSkill;
	        int level = SkillWebUtils.getLevel(request);
	        if (skillRatingSet != null) {
	            if (level == 0) {
	                //forceAllChildrenToDisplay = true;
	               log.debug("doRender() - adding implied skills to skillSet. Level is 0");
	               SkillSetUtil util = null;
	           		util = new SkillSetUtil(skillRatingSet, rootSkill);
           			util.addImpliedParentSkills();
	            }
	        	if (log.isDebugEnabled()) {
	        		log.debug("After adding implied ratings" 
	        				+ "\r\n" + skillRatingSet.toString());
	        	}
	            html += getSpecificSkillsEntry(skillRatingSet, skillSet, 
	            		parentSkill, level);
	        }
    	}
    	catch (Exception ex) {
    		log.error("Exception in doStartTag()", ex);
    		throw new SystemException("Exception in doStartTag()", ex);
    	}
		return(html);
		
    }
    
    
    private boolean isOnBranch(Skill child) {
    	boolean result = false;
    	if (this.skillBranch == null) {
    		result = true;
    	}
    	else {
    		Skill parentSkill = child;
    		while ((result == false) && (parentSkill != null)) {
    			if (parentSkill.getCode().equals(skillBranch.getCode())) {
    				result = true;
    				parentSkill = parentSkill.getSkillParent();
    			}
    		}
    	}
    	return(result);
    }


    public String getSpecificSkillsEntry(SkillRatingSet owner, Collection skillSet, Skill baseSkill, int level)
    {
        log.debug("getSpecificSkillsEntry() - called");
        Form form = new Form();
        form.setMethod("get");
        form.setAction(getFormAction());
        form.addHidden("ownerId", getOwnerObjectId());
        form.setAcceptCharset(Form.NO_ATTRIBUTE_VALUE);
        form.setEncType("multipart/form-data");
        addHiddenInputs(form);
        
        form.addHidden("level", "" + level);        

        if (level == 0) {
            log.debug("getSpecificSkillsEntry() - level is '0' - displaying top level topics.");
            showSkillChildrenRatingEntry(owner, skillSet, rootSkill, form);
        } else {
            log.debug("getSpecificSkillsEntry() - displaying lower level topics.");
            List skillList = TreeHelper.getChildrenAtLevel(baseSkill, level - 1);
            log.debug("getSpecificSkillsEntry() - child count at current level: " + skillList.size());

            try {            
                Iterator iter = skillList.iterator();
                while (iter.hasNext()) {
                    Skill parentSkill = (Skill)iter.next();
                    if (isOnBranch(this.skillBranch)) {
	                    SkillSetUtil util = new SkillSetUtil(owner, rootSkill);
	
	                    if ((util.hasSkillRatingInBranch(parentSkill)) 
									|| (parentSkill.getCode().equals(rootSkill.getCode()))) {
	                        log.debug("getSpecificSkillsEntry() - showing children of: " 
	                        		+ parentSkill.getDescription());
	                        showSkillChildrenRatingEntry(owner, skillSet, parentSkill, form);
	                        log.debug("getSpecificSkillsEntry() - called 1.6");
	                    } else {
	                        log.debug("getSpecificSkillsEntry() - entity does not have branch skill: " 
	                        		+ parentSkill.getCode());
	                    }
                    }
                }
            }
            catch (Exception ex) {
                log.error("Exception during display of skills.", ex);
            }
        }
        
        form.addElement("<br>");
        if (level > 0) {
        	String  buttonStr = 
        		"<input type=\"image\" src=\"" +
        		    this.getContextPath() + "/dynagraphic/button.jpg?code=button.param&caption=" 
        			+  this.getPhrase("button.previous") + "\" border=\"0\" value=\"previous\" name=\"previous\" />";
/*        	
            Input input = new Input();
            input.setType(Input.SUBMIT);
            input.setClass("formButton");        
            input.setName("prev_btn");
            input.setValue("Previous");
            form.addElement(input);
            form.addElement("&nbsp;");
            */
        	form.addElement(buttonStr);
        }
        
		String nextButton = "<input type=\"image\" src=\"" +
				this.getContextPath() + "/dynagraphic/button.jpg?code=button.param&caption=" 
        	+  this.getPhrase("button.next") + "\" border=\"0\" value=\"next\" name=\"next\" />";
/*        
        Input input = new Input();
        input.setType(Input.SUBMIT);
        input.setClass("formButton");        
        input.setName("next_btn");
        input.setValue("Next");
        form.addElement(input);
        */
		form.addElement(nextButton);
        
        log.debug("getSpecificSkillsEntry() - finished");

        return(form.toString());

    };
    
    
    // Enter more specific information for each major skill
    private void showSkillChildrenRatingEntry(SkillRatingSet owner, Collection skillSet, 
    		Skill skill, Form form)
    {
    	if (log.isDebugEnabled())
    		log.debug("showSkillChildrenRatingEntry() - called: " + skill.getCode());
        
        BorderTable table = null;
        if (skill == null) {
            log.error("showSkillChildrenRatingEntry() - skill is null");
        }
        else {
            log.debug("showSkillChildrenRatingEntry() - called.  Parent Skill = " + skill.getId());
            boolean firstRatingEntry = true;
            TreeSet children = new TreeSet(new SkillChildComparator());
            children.addAll(skill.getChildren());
            
            Iterator childIter = children.iterator();
            while (childIter.hasNext()) {
                Skill childSkill = (Skill)childIter.next();
                if ((skillBranch == null) || (this.isOnBranch(childSkill))) {
	                if (log.isDebugEnabled()) {
	                    log.debug("showSkillChildrenRatingEntry() - displaying skill: " + childSkill.getId());
	                }
	                if (firstRatingEntry) {
	                    firstRatingEntry = false;
	        
	                    IMG downImg = new IMG();
	                    downImg.setSrc("/recruit/graphics/skill_down.gif");
	                    downImg.setAlt("|");
	                    form.addElement(TextHelper.getFont("header3", "<br><br><b>" + skill.getDescription() + "</b>"));
	        
	                    table = new BorderTable();
	                    table.setWidth(tableWidth);
	                    table.setCellSpacing(0);
	                    form.addElement(table);
	        
	                    log.debug("Building specific skill entry table");
	                        
	                    table.setCellSpacing(0);
	                    table.setBgColor("#F0F0F0");
	                    table.setWidth(getWidth());
	        
	                    Row row1 = table.addRow();
	    		        row1.setDefaultBgImage(this.getContextPath() + "/site-graphics/tbl_hdr.gif");
	        
	                    Cell cell2 = row1.addCell();
	                    cell2.setWidth(300);
	                    Font text2 = new Font();
	                    text2.setClass("tableHdrFont");
	                    text2.addElement("<b>Description</b>");
	                    cell2.addElement(text2);
	    
	              /*      
	                    Cell cellYesNo = row1.addCell();
	                    Font textYesNo = new Font();
	                    textYesNo.setClass("smlTblHeader");
	                    textYesNo.addElement("<b>View Children</b>");
	                    cellYesNo.addElement(textYesNo);
	                    cellYesNo.setWidth(200);
	*/
	                    Cell cell3 = row1.addCell();
	                    Font text3 = new Font();
	                    
	                    text3.setClass("tableHdrFont");
	                    text3.addElement("<b>Skill Level</b>");
	                    cell3.addElement(text3);
	                    cell3.setWidth(200);
	
	                    
	                    /*
	                    if (job != null) {
	                        Cell cellYears = row1.addCell();
	                        Font textYears = new Font();
	                        textYears.setClass("smlTblHeader");
	                        textYears.addElement("<b>Required Years</b>");
	                        cellYears.addElement(textYears);
	                        cellYears.setWidth(200);
	                    }
	                    */
	/*                    
	                    Cell cell4 = row1.addCell();
	                    Font text4 = new Font();
	                    text4.setClass("smlTblHeader");
	                    text4.addElement("<b>Interest Level</b>");
	                    cell4.addElement(text4);
	                    cell4.setWidth(200);
	  */                  
	                };
	                log.debug("showSkillChildrenRatingEntry() - finished with skill header info - now showing current rating...");
	                showSkillRating(owner, skillSet, skill, childSkill, form, table);
	                firstRatingEntry = false;
                }
            }
        }
    }

    
    private boolean showSkillRating(SkillRatingSet owner, Collection skillSet, Skill parentSkill, Skill childSkill, 
                Form form, BorderTable table) {
        boolean displayed = false;
        boolean entryCreated = false;

        if (log.isDebugEnabled()) {
            log.debug("showSkillRating() - displaying skill: " + childSkill.getDescription());
            log.debug("showSkillRating() - scoring method: " + childSkill.getScoringMethod().getDescription());
        }
            
        log.debug("showSkillRating() called");
        displayed = true;
        
        log.debug("Setting up rating entry visual components for skill: " + childSkill.getDescription());

        Row row1 = table.addRow();
        log.debug("showSkillRating() - 1.0");
        Cell labelCell = row1.addCell();
        Font text2 = new Font("#FFFFFF", 2);
        text2.addElement(TextHelper.getFont("stdFont", childSkill.getDescription()));
        labelCell.addElement(text2);
        
        Cell ratingCell = row1.addCell();

        log.debug("showSkillRating() - 2.0");
        

        
        try {
            SkillRating rating = null;
            rating = owner.findSkillRating(childSkill);
            
            if (rating == null)
                log.debug("No existing rating for: " + childSkill.getCode());
            else {
                log.debug("Rating found for: " + childSkill.getCode()
                        + rating.toString());
            }
    
    
    /*
            // ALways show the skill levels for every node for a job.
            if ((childSkill.getNeedsLevel()) || (job != null)) {
                Table ratingTable = SkillGui.makeSkillLevelTable(rating, childSkill);
                ratingCell.addElement(ratingTable);
                entryCreated = true;        
            }
    */
    

             if (this.getShowRating()) { 
                log.debug("showSkillRating() - making check box for skill");
            	
            	if ((childSkill.getScoringMethod().getCode().equals(SkillScoringMethod.SCORING_METHOD_LEVEL)) || (this.alwaysShowLevelEntry())) {
            		Table levelTable = SkillGui.makeSkillLevelTable(rating, childSkill);
            		ratingCell.addElement(levelTable);
            		entryCreated = true;
            	}
            	if ((entryCreated == false) && (this.alwaysShowLevelEntry() == false)) {
	            	if ((childSkill.getScoringMethod().getCode().equals(SkillScoringMethod.SCORING_METHOD_YES_NO)) 
	            			|| (childSkill.getScoringMethod().getCode().equals(SkillScoringMethod.SCORING_METHOD_NONE))){
	            		SkillGui.displayYesNo(rating, childSkill, ratingCell);
	            		entryCreated = true;
	            	//} else if (childSkill.getScoringMethod().getCode().equals(Skill.SCORING_METHOD_YEARS)) {
	            	//	SkillGui.displayYears(rating, childSkill, ratingCell);
	            	//	entryCreated = true;
	            	} else {
	            		throw new SystemException("Do not know how to handle skill scoring method: "
	            				+ childSkill.getScoringMethod().getDescription() 
								+ "  Skill = " + childSkill.getCode());
	            	}
            	}
            	
            	if ((entryCreated == false) && (childSkill.getChildren().size() > 0)) {
            		SkillGui.displayYesNo(rating, childSkill, ratingCell);
            		entryCreated = true;
            	}
            			
        	}
            
            // Make interest level
            //Cell cell4 = row1.addCell();
            //cell4.addElement(makeInterestLevelTable(rating, childSkill));
            //SkillGui.displayYesNo(rating, childSkill, cell4);
            
            
        }
        catch (Exception ex) {
            log.error("Exception displaying rating.", ex);
        }
        
        return(displayed);
    }

    
    
    private void displayViewChildren(SkillRating rating, Skill skill, Cell cell) {
        if (skill.getChildren().size() > 0) {
            log.debug("showSkillRating() - making check box for skill");
            Input input = new Input();
            input.setType(Input.CHECKBOX);
            input.setName("children_" + skill.getCode());
    
            if (rating != null) {
                if (skill.getScoringMethod().getCode().equals(SkillScoringMethod.SCORING_METHOD_YES_NO)) {
                    input.setChecked(rating.hasSkill());
                }
                else {
                    input.setChecked(true);
                }
            }
            else {
                input.setChecked(false);
            }
            cell.addElement(input);
            cell.addElement(TextHelper.getFont("subFont", "View Children"));
        }
    }
    
    
/*    
    private Table makeInterestLevelTable(SkillRating rating, Skill childSkill) {
        Table table = new Table();
        table.setCellSpacing(0);
        table.setCellPadding(0);
        Row row = table.addRow();
        Cell cell = row.addCell();
        cell.addElement(TextHelper.getFont("tinyFont", "No Interest&nbsp;"));
        cell.setVAlign("middle");
        row.addElement(makeInterestRadio(0, rating, childSkill));
        row.addElement(makeInterestRadio(1, rating, childSkill));
        row.addElement(makeInterestRadio(2, rating, childSkill));
        row.addElement(makeInterestRadio(3, rating, childSkill));
        row.addElement(makeInterestRadio(4, rating, childSkill));
        cell = row.addCell();
        cell.setVAlign("middle");
        cell.addElement(TextHelper.getFont("tinyFont", "&nbsp;Extremely Interested"));
        
        return(table);
    }

    
    private Cell makeInterestRadio(int level, SkillRating rating, Skill childSkill) {
        Cell cell = new Cell();
        cell.setVAlign("top");
        Input radio = new Input();
        radio.setType(Input.RADIO);
        radio.setName("int_" + childSkill.getSkillCode());
        radio.setValue("" + level);
        if (rating != null) {
            if (level == rating.getWeight()) 
                radio.setChecked(true);
        }
        else if (level == 0) {  // // User has no rating, default display to "none" 
            radio.setChecked(true);
        }
        cell.addElement(radio);
        return(cell);
    }
*/
}